#pragma once

#include <iostream>
#include <string>
#include <string.h>
#include <cstdio>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "Time.hpp"
#include "Fifo.hpp"

using namespace std;

// 文件路径
const string path = "/home/gan/code/new_w/lesson23/2.sharemem";
// 项目ID
int projId = 0x6666;
// 创建共享内存的大小
int gShmSize = 4096;
// 默认权限
mode_t gMode = 0600;

// 将10进制转换为16进制
string ToHex(key_t k)
{
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "%x", k);
    return buffer;
}

class ShareMemory
{
private:
    // 提供代码复用性 精简代码
    void CreateShmHelper(int shmFlg)
    {
        // 生成键
        _key = ::ftok(path.c_str(), projId);
        if (_key < 0)
        {
            cerr << "ftok error" << endl;
            return;
        }

        // 创建共享内存
        _shmid = ::shmget(_key, gShmSize, shmFlg);
        if (_shmid < 0)
        {
            // 创建失败
            cerr << "shmget error" << endl;
            return;
        }
        cout << "shmid: " << _shmid << endl;
    }

public:
    ShareMemory()
        : _shmid(-1), _key(0), _addr(nullptr)
    {
    }

    ~ShareMemory()
    {
    }

    // 创建共享内存
    void CreateShm()
    {
        if (_shmid == -1)
        {
            // 传入对应权限即可
            CreateShmHelper(IPC_CREAT | IPC_EXCL | gMode);
        }
        cout << "key: " << ToHex(_key) << endl;
    }

    // 获取共享内存 不创建
    void GetShm()
    {
        CreateShmHelper(IPC_CREAT | gMode);
    }

    // 挂接共享内存
    void AttachShm()
    {
        _addr = shmat(_shmid, nullptr, 0);
        if ((long long)_addr == -1)
        {
            cout << "attach error" << endl;
            return;
        }
    }

    // 去关联共享内存
    void DetachShm()
    {
        if (_addr != nullptr)
        {
            ::shmdt(_addr);
        }
    }

    // 删除共享内存
    void DeleteShm()
    {
        shmctl(_shmid, IPC_RMID, nullptr);
    }

    void* GetAddr()
    {
        return _addr;
    }

    // 获取共享内存的属性
    void ShmMeta()
    {
        struct shmid_ds buffer; //系统提供的数据类型
        // 获取属性 输出到buffer中
        int n = ::shmctl(_shmid, IPC_STAT, &buffer);
        if (n < 0)
            return;
        
        cout << "########################" << endl;
        cout << buffer.shm_atime << endl; // 最后attach时间
        cout << buffer.shm_cpid << endl;  // 创建该共享内存段的进程ID
        cout << buffer.shm_ctime << endl; // 创建时间
        cout << buffer.shm_nattch << endl;// 该共享内存的挂接进程数
        cout << ToHex(buffer.shm_perm.__key) << endl; // 其键值转换为16进制
        cout << "########################" << endl;
    }

private:
    int _shmid;
    key_t _key;
    void *_addr;
};

// 初始化一个共享内存对象
ShareMemory shm;

struct data
{
    char status[32];
    char lasttime[48];
    char image[4000];
};